package com.jhgsys.internal.incentive.controller;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jhgsys.internal.base.entity.BaseGoods;
import com.jhgsys.internal.base.service.IBaseGoodsService;
import com.jhgsys.internal.common.annotation.Log;
import com.jhgsys.internal.common.constant.ModuleManagerPermissionConstant;
import com.jhgsys.internal.common.controller.BaseController;
import com.jhgsys.internal.common.entity.FebsConstant;
import com.jhgsys.internal.common.entity.FebsResponse;
import com.jhgsys.internal.common.entity.QueryRequest;
import com.jhgsys.internal.common.exception.FebsException;
import com.jhgsys.internal.common.utils.FebsUtil;
import com.jhgsys.internal.incentive.constant.IncentiveRewardConstant;
import com.jhgsys.internal.incentive.dto.IncentiveRewardApplyDto;
import com.jhgsys.internal.incentive.entity.*;
import com.jhgsys.internal.incentive.service.IIncentiveGoodsOrderService;
import com.jhgsys.internal.incentive.service.IIncentiveQuotaConfigService;
import com.jhgsys.internal.incentive.service.IIncentiveRewardApplyService;
import com.jhgsys.internal.incentive.service.IIncentiveRewardConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Date;

/**
 * 安全奖励申请 Controller
 *
 * @author wanghjw
 * @date 2024-09-03 14:08:36
 */
@Slf4j
@Validated
@Controller
public class IncentiveRewardApplyController extends BaseController {

    @Autowired
    private IIncentiveRewardApplyService incentiveRewardApplyService;

    @Autowired
    private IIncentiveQuotaConfigService incentiveQuotaConfigService;

    @Autowired
    private IIncentiveRewardConfigService incentiveRewardConfigService;

    @Autowired
    private IIncentiveGoodsOrderService incentiveGoodsOrderService;



    @Autowired
    private IBaseGoodsService goodsService;

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply")
    @RequiresPermissions("incentiveRewardApply:view")
    public String incentiveRewardApplyIndex(Model model) {
        model.addAttribute("hasHeadCompanyRole", hasHeadCompanyRole());
        model.addAttribute("tenantList", getTenantList());
        model.addAttribute("currentTenantId", getCurrentTenantId());
        model.addAttribute("quotaConfig", getCanUseQuotaConfig());
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardApplyList");
    }

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply/add")
    @RequiresPermissions("incentiveRewardApply:add")
    public String incentiveRewardApplyAdd(Model model) {
        model.addAttribute("quotaConfig", getCanUseQuotaConfig());
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardApplyEdit");
    }

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply/update/{id}")
    @RequiresPermissions("incentiveRewardApply:edit")
    public String incentiveRewardApplyUpdate(Model model, @PathVariable("id") String id) throws JsonProcessingException {
        IncentiveRewardApplyDto dto = incentiveRewardApplyService.findIncentiveRewardApplyById(id);
        model.addAttribute("incentiveRewardApply", JSON.parse(new ObjectMapper().writeValueAsString(dto)));
        model.addAttribute("quotaConfig", getCanUseQuotaConfig());
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardApplyEdit");
    }

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply/detail/{id}")
    @RequiresPermissions("incentiveRewardApply:view")
    public String incentiveRewardApplyDetail(Model model, @PathVariable("id") String id) throws JsonProcessingException {
        IncentiveRewardApplyDto dto = incentiveRewardApplyService.findIncentiveRewardApplyById(id);
        model.addAttribute("incentiveRewardApply", JSON.parse(new ObjectMapper().writeValueAsString(dto)));
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardDetail");
    }

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply/delete/{id}")
    @RequiresPermissions("incentive:manager")
    public String incentiveRewardApplyDelete(Model model, @PathVariable("id") String id) throws JsonProcessingException {
        IncentiveRewardApplyDto dto = incentiveRewardApplyService.findIncentiveRewardApplyById(id);
        model.addAttribute("incentiveRewardApply", JSON.parse(new ObjectMapper().writeValueAsString(dto)));
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardDelete");
    }

    @GetMapping(FebsConstant.VIEW_PREFIX + "incentiveRewardApply/receive/{id}")
    @RequiresPermissions("incentiveRewardApply:upload")
    public String incentiveRewardApplyupload(Model model, @PathVariable("id") String id) throws JsonProcessingException {
        IncentiveRewardApplyDto dto = incentiveRewardApplyService.findIncentiveRewardApplyById(id);
        model.addAttribute("incentiveRewardApply", JSON.parse(new ObjectMapper().writeValueAsString(dto)));
        return FebsUtil.view("incentive/incentiveRewardApply/incentiveRewardUpload");
    }


    /**
     * 查询（所有）
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @GetMapping("incentiveRewardApply")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:view")
    public FebsResponse getAllIncentiveRewardApplys(IncentiveRewardApply incentiveRewardApply) {
        return new FebsResponse().success().data(incentiveRewardApplyService.findIncentiveRewardApplyList(incentiveRewardApply));
    }

    /**
     * 查询（分页）
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @GetMapping("incentiveRewardApply/list")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:view")
    public FebsResponse incentiveRewardApplyList(QueryRequest request, IncentiveRewardApplyDto incentiveRewardApply) {
        if(!hasHeadCompanyRole()){
            incentiveRewardApply.setApplyUserId(getCurrentUserId());
        }

        Map<String, Object> dataTable = getDataTable(this.incentiveRewardApplyService.findIncentiveRewardApplyPage(request, incentiveRewardApply));
        return new FebsResponse().success().data(dataTable);
    }

    /**
     * 新增 IncentiveRewardApply
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @Log("新增安全奖励申请")
    @PostMapping("incentiveRewardApply")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:add")
    public FebsResponse addIncentiveRewardApply(@RequestBody IncentiveRewardApplyDto incentiveRewardApply) throws FebsException {
        checkParams(incentiveRewardApply);
        try {
            if (!checkUsefulQuota(incentiveRewardApply)) {
                return new FebsResponse().fail().message("剩余额度不足，请先申请额度或者减少奖励内容");
            }
            incentiveRewardApply.setRewardApplyNo(incentiveRewardApplyService.createIncentiveRewardApplyNo(incentiveRewardApply.getTenantId()));

            incentiveRewardApply.setApplyUserId(getCurrentUserId());
            incentiveRewardApply.setApplyUserNo(getCurrentUser().getUserName());
            incentiveRewardApply.setApplyData(new Date());
            incentiveRewardApply.setApplyRealName(getCurrentUser().getUname());

            incentiveRewardApply.setCreatedBy(getCurrentUser().getUserName());
            this.incentiveRewardApplyService.createIncentiveRewardApply(incentiveRewardApply);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "新增安全奖励申请失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    /**
     * 逻辑删除 IncentiveRewardApply
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @Log("逻辑删除安全奖励申请")
    @GetMapping("incentiveRewardApply/delete/{id}")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:delete")
    public FebsResponse deleteIncentiveRewardApply(@PathVariable("id") String incentiveRewardApplyIds) throws FebsException {
        try {
            IncentiveRewardApply incentiveRewardApply = new IncentiveRewardApply();
            incentiveRewardApply.setDeletedBy(getCurrentUser().getUserName());
            incentiveRewardApply.setDeletedTime(new Date());
            incentiveRewardApply.setDeletedFlg(FebsConstant.INVALID);
            this.incentiveRewardApplyService.deleteIncentiveRewardApply(incentiveRewardApply, incentiveRewardApplyIds);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "删除安全奖励申请失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }


    /**
     * 修改 IncentiveRewardApply
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @Log("修改安全奖励申请")
    @PostMapping("incentiveRewardApply/update")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:edit")
    public FebsResponse updateIncentiveRewardApply(@RequestBody IncentiveRewardApplyDto incentiveRewardApply) throws FebsException {
        checkParams(incentiveRewardApply);
        if (StringUtils.isBlank(incentiveRewardApply.getRewardApplyId())) {
            throw new FebsException("奖励申请ID不能为空");
        }
        try {
            IncentiveRewardApply queryData = this.incentiveRewardApplyService.findIncentiveRewardApplyById(incentiveRewardApply.getRewardApplyId());
            if (ObjectUtils.isEmpty(queryData)) {
                return new FebsResponse().fail().message("找不到待更新记录");
            }
            if (!IncentiveRewardConstant.APPLY_STATUS.UPLOAD.equals(queryData.getStatus())) {
                return new FebsResponse().fail().message("该申请无法被更新，请刷新后重试");
            }

            if (!checkUsefulQuota(incentiveRewardApply)) {
                return new FebsResponse().fail().message("剩余额度不足，请先申请额度或者减少奖励内容");
            }
            if (IncentiveRewardConstant.APPLY_STATUS.WAIT_AUDIT.equals(incentiveRewardApply.getStatus())) {
                incentiveRewardApply.setApplyUserId(getCurrentUserId());
                incentiveRewardApply.setApplyUserNo(getCurrentUser().getUserName());
                incentiveRewardApply.setApplyData(new Date());
                incentiveRewardApply.setApplyRealName(getCurrentUser().getUname());
            }
            incentiveRewardApply.setUpdatedBy(getCurrentUser().getUserName());
            this.incentiveRewardApplyService.updateIncentiveRewardApply(incentiveRewardApply);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "修改安全奖励申请失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    /**
     * 管理员删除安全奖励申请
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @Log("管理员删除安全奖励申请")
    @PostMapping("incentiveRewardApply/delete")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:edit")
    public FebsResponse updateIncentiveRewardApplyDelete(@RequestBody IncentiveRewardApply incentiveRewardApply) throws FebsException {
        if (StringUtils.isBlank(incentiveRewardApply.getRewardApplyId())) {
            throw new FebsException("奖励申请ID不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getDeletedRemark())) {
            throw new FebsException("删除备注不能为空");
        }
        try {
            IncentiveRewardApply queryData = this.incentiveRewardApplyService.findIncentiveRewardApplyById(incentiveRewardApply.getRewardApplyId());
            if (ObjectUtils.isEmpty(queryData)) {
                return new FebsResponse().fail().message("找不到待删除记录");
            }
            if (!FebsConstant.VALID.equals(queryData.getDeletedFlg())) {
                return new FebsResponse().fail().message("该申请无法被删除，请刷新后重试");
            }

            //如果不是待提交，待审核，审核退回，则查询实物发放表
            if(!IncentiveRewardConstant.APPLY_STATUS.UPLOAD.equals(queryData.getStatus())
                    && !IncentiveRewardConstant.APPLY_STATUS.WAIT_AUDIT.equals(queryData.getStatus())
                    && !IncentiveRewardConstant.APPLY_STATUS.FAIL_AUDIT.equals(queryData.getStatus())){
                IncentiveGoodsOrder incentiveGoodsOrder = new IncentiveGoodsOrder();
                incentiveGoodsOrder.setRewardApplyId(incentiveRewardApply.getRewardApplyId());
                List<IncentiveGoodsOrder> queryOrderList = incentiveGoodsOrderService.findIncentiveGoodsOrderList(incentiveGoodsOrder);
                if(!CollectionUtils.isEmpty(queryOrderList)){
                    if(!queryOrderList.get(0).equals(IncentiveRewardConstant.ORDER_STATUS.WAIT_RECEIVE)){
                        return new FebsResponse().fail().message("该申请奖励物品已发放，无法被删除，请联系管理员");
                    }
                }
            }

            incentiveRewardApply.setDeletedBy(getCurrentUser().getUserName());
            incentiveRewardApply.setDeletedTime(new Date());
            incentiveRewardApply.setDeletedFlg(FebsConstant.INVALID);
            incentiveRewardApply.setRewardGoodsFlg(null);
            incentiveRewardApply.setRewardAmountFlg(null);
            incentiveRewardApply.setRewardScoreFlg(null);
            this.incentiveRewardApplyService.saveOrUpdate(incentiveRewardApply);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "删除安全奖励申请失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }


    /**
     * 管理员删除安全奖励申请
     *
     * @author wanghjw
     * @date 2024-09-03 14:08:36
     */
    @Log("管理员删除安全奖励申请")
    @PostMapping("incentiveRewardApply/receive")
    @ResponseBody
    @RequiresPermissions("incentiveRewardApply:upload")
    public FebsResponse receiveIncentiveRewardApply(@RequestBody IncentiveRewardApplyDto incentiveRewardApply) throws FebsException {
        if (StringUtils.isBlank(incentiveRewardApply.getRewardApplyId())) {
            throw new FebsException("奖励申请ID不能为空");
        }
        if (CollectionUtils.isEmpty(incentiveRewardApply.getReceiveFileList())) {
            throw new FebsException("签收文件不能为空");
        }
        try {
            IncentiveRewardApply queryData = this.incentiveRewardApplyService.findIncentiveRewardApplyById(incentiveRewardApply.getRewardApplyId());
            if (ObjectUtils.isEmpty(queryData)) {
                return new FebsResponse().fail().message("找不到待签收记录");
            }

            IncentiveGoodsOrder incentiveGoodsOrder = new IncentiveGoodsOrder();
            incentiveGoodsOrder.setRewardApplyId(incentiveRewardApply.getRewardApplyId());
            List<IncentiveGoodsOrder> queryOrderList = incentiveGoodsOrderService.findIncentiveGoodsOrderList(incentiveGoodsOrder);
            if(!CollectionUtils.isEmpty(queryOrderList)){
//                if(!queryOrderList.get(0).equals(IncentiveRewardConstant.ORDER_STATUS.WAIT_RECEIVE)){
//                    return new FebsResponse().fail().message("该申请奖励物品已发放，无法被重复签收，请联系管理员");
//                }
            }else{
                return new FebsResponse().fail().message("未找到该申请单对应订单！请联系管理员");
            }

            this.incentiveRewardApplyService.receiveIncentiveRewardApply(incentiveRewardApply,queryOrderList.get(0));
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "安全奖励上传签收附件失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }


    /**
     * 参数校验
     * @param incentiveRewardApply
     * @throws FebsException
     */
    private void checkParams(IncentiveRewardApplyDto incentiveRewardApply) throws FebsException {

        if (CollectionUtils.isEmpty(incentiveRewardApply.getUserList())) {
            throw new FebsException("被奖励人员不能为空");
        }

        if (StringUtils.isBlank(incentiveRewardApply.getRewardType())) {
            throw new FebsException("奖励类型不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getRewardClauseId())) {
            throw new FebsException("条款类型Id不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getRewardClause())) {
            throw new FebsException("条款名称不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getRewardClauseRuleId())) {
            throw new FebsException("条款类规则Id不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getRewardClauseRule())) {
            throw new FebsException("条款类规则内容不能为空");
        }
        if (StringUtils.isBlank(incentiveRewardApply.getStatus())) {
            throw new FebsException("状态不能为空");
        }

        if (StringUtils.isBlank(incentiveRewardApply.getRewardAmountFlg())) {
            throw new FebsException("奖励金额标识不能为空");
        }
        if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardAmountFlg())) {
            if (ObjectUtils.isEmpty(incentiveRewardApply.getRewardAmount())) {
                throw new FebsException("奖励金额不能为空");
            }
        }
        if (StringUtils.isBlank(incentiveRewardApply.getRewardGoodsFlg())) {
            throw new FebsException("奖励商品标识不能为空");
        }
        if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardGoodsFlg())) {
            if (CollectionUtils.isEmpty(incentiveRewardApply.getGoodsList())) {
                throw new FebsException("奖励商品不能为空");
            }
        }

        if (StringUtils.isBlank(incentiveRewardApply.getRewardScoreFlg())) {
            throw new FebsException("奖励积分标识不能为空");
        }
        if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardScoreFlg())) {
            if (ObjectUtils.isEmpty(incentiveRewardApply.getRewardScore())) {
                throw new FebsException("奖励积分不能为空");
            }
        }

    }


    /**
     * 校验奖励额度和剩余额度
     *
     * @param incentiveRewardApply
     * @return
     */
    private boolean checkUsefulQuota(IncentiveRewardApplyDto incentiveRewardApply) {
        //是否有足够的剩余额度
        boolean canApply = true;
        //本次使用额度
        BigDecimal useQuota = new BigDecimal(0);
        //获取用户当年额度设置
        IncentiveQuotaConfig config = getCanUseQuotaConfig();
        if (!ObjectUtils.isEmpty(config)) {
            BigDecimal rewardedQuota = ObjectUtils.isEmpty(config.getRewardedQuota()) ? new BigDecimal(0) : config.getRewardedQuota();
            //计算可用剩余额度
            BigDecimal canUse = config.getTotalQuota().subtract(rewardedQuota);

            //人数
            BigDecimal personNum = new BigDecimal(incentiveRewardApply.getUserList().size());


            //奖励金额
            if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardAmountFlg())) {
                //消费额度为 人数* 金额
                useQuota = incentiveRewardApply.getRewardAmount().multiply(personNum);
                //如果奖励金钱，则判断奖励金额和适用额额度
                if (canUse.compareTo(useQuota) == -1) {
                    canApply = false;
                }
            }

            //奖励商品
            if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardGoodsFlg())) {
                List<IncentiveRewardGoods> rewardGoods = incentiveRewardApply.getGoodsList();
                //编辑商品列表，获取对应商品单价 单价*数量
                for (IncentiveRewardGoods item : rewardGoods) {
                    BaseGoods goods = goodsService.findBaseGoodsById(item.getGoodsId());
                    //商品使用额度 = 单价* 数量*人数
                    BigDecimal gooddAmount = goods.getGoodsPrice().multiply(new BigDecimal(item.getGoodsNumber())).multiply(personNum);
                    useQuota.add(gooddAmount);
                }
                if (canUse.compareTo(useQuota) == -1) {
                    canApply = false;
                }

            }

            //奖励积分
            if (IncentiveRewardConstant.IS_OR_NO.IS.equals(incentiveRewardApply.getRewardScoreFlg())) {
                //如果奖励积分，则先获取积分转换汇率，如果未配置积分转化汇率，则直接扣除
                IncentiveRewardConfig rewardConfig = incentiveRewardConfigService
                        .findIncentiveRewardConfigByTenantId(incentiveRewardApply.getTenantId());
                if (ObjectUtils.isNotEmpty(rewardConfig) && ObjectUtils.isNotEmpty(rewardConfig.getScoreAmountRatio())) {
                    //使用积分 = 积分*比例*人数
                    BigDecimal needScore = rewardConfig.getScoreAmountRatio()
                            .multiply(new BigDecimal(incentiveRewardApply.getRewardScore()))
                            .multiply(personNum);
                    useQuota = useQuota.add(needScore);
                    if (canUse.compareTo(useQuota) == -1) {
                        canApply = false;
                    }
                } else {
                    //无比例配置情况下 积分*人数
                    useQuota = useQuota.add(new BigDecimal(incentiveRewardApply.getRewardScore()).multiply(personNum));
                    if (canUse.compareTo(useQuota) == -1) {
                        canApply = false;
                    }
                }
            }
        } else {
            //如果用户当年没有额度设置，则无法申请
            canApply = false;
        }
        incentiveRewardApply.setRewardedQuota(useQuota);
        return canApply;
    }


    /**
     * 获取奖励额度设置
     *
     * @return
     */
    private IncentiveQuotaConfig getCanUseQuotaConfig() {
        IncentiveQuotaConfig config = new IncentiveQuotaConfig();
        config.setTenantId(getCurrentTenantId());
        config.setUserId(getCurrentUserId());
        config.setYear(LocalDate.now().getYear());
        config.setStatus(IncentiveRewardConstant.IS_OR_NO.IS);
        List<IncentiveQuotaConfig> configList = incentiveQuotaConfigService.findIncentiveQuotaConfigList(config);
        if (!CollectionUtils.isEmpty(configList)) {
            return configList.get(0);
        } else {
            return null;
        }

    }
}
